/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pbb_template_updater;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 *
 * @author jhuss
 */
public class PbbUpdater {

    //Useful for Debugging...
    //public static final String pageBase = "User:JonSDSUGrad/Sandbox/Demo_";
    //public static final String pageBase = "";
    private String pageBase;
    public static final boolean debugUpload = false;
    public static final boolean EXPERIMENT = true;
    private String matchGridPageData = "";
    private String lineSep = null;
    private Vector<String> miniLog;
    //Global Variables:
    //flags for program operation:
    String glblConfigFile = null;
    PbbConfig glblConfiguration = null;
    boolean glblParseGoTerms;
    //PbbQuickLog glblBotLog = null;
    PbbFileIO glblFileIO = null;
    Hashtable<String, String> glblPageLocations;
    Hashtable<String, String> glblPageTitles;
    PbbWikiCom glblWikiCom = null;
    PbbXML glblXmlParser = null;
    //PBBCitation glblCitation = null;
    //Means this protein had an error while processing and was skipped
    //helps us create a list of skipped proteins for later processing.
    Hashtable<String, Boolean> glblProteinErrors;
    String glblRunLogPage; //based on glblConfiguration.getWikiLogRun();

    //used to track what happens with each protein.  Does the protein create a new page?
    //Does is get skipped because of an Error or because of No Bots?  that kind of stuff.
    private enum pStatus {

        Skip_no_bots {

            @Override
            String text() {
                return "Manual Inspection (NO BOTS tag)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_no_change {

            String text() {
                return "No Update Needed, Data did not change.";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_error {

            String text() {
                return "Manual Inspection (Unknown Error)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_tag_error {

            String text() {
                return "Manual Inspection (Parsing Error)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_no_update {

            String text() {
                return "Manual Inspection (Updates Off)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_manual_insp {

            String text() {
                return "Manual Inspection (Control Box)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        created {

            String text() {
                return "Created";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        unresolved {

            String text() {
                return "Unresolved Status";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        Skip_amb_page {

            String text() {
                return "Manual Inspection (Page not found)";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        updated_warning {

            String text() {
                return "Updated with Warning";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            int getPCount() {
                return count;
            }
        },
        updated {

            String text() {
                return "Updated";
            }
            int count = 0;

            void setPCount(int x) {
                count = x;
            }

            @Override
            int getPCount() {
                return count;
            }
        };

        abstract String text();

        abstract void setPCount(int x);

        abstract int getPCount();
    }
    //8,15,17,20,10
    private Hashtable<String, pStatus> glblProteinStatus;

    /** Creates a new instance of ProteinBoxBot */
    public PbbUpdater(String ConfigFileLocation, boolean pgt) {

        miniLog = new Vector<String>();

        glblProteinStatus = new Hashtable<String, pStatus>();
        glblParseGoTerms = pgt;
        glblConfigFile = ConfigFileLocation;
        lineSep = System.getProperty("line.separator");
        //glblBotLog = null;
        glblPageLocations = new Hashtable<String, String>();
        glblPageTitles = new Hashtable<String, String>();
        glblProteinErrors = new Hashtable<String, Boolean>();

        //First check to see if the configuration file can be parsed.
        try {
            glblConfiguration = new PbbConfig(glblConfigFile);

        } catch (Exception e) {
            System.out.println("Error while Parsing Config File:");
            System.out.println(e.getMessage());
            e.printStackTrace();
            //this.cleanUp();
            //e.printStackTrace();
            System.exit(1);
        }



        glblFileIO = new PbbFileIO();
        //Ok, so we are going to get a list of geneIds from the input file.
        //we then download the XML data and store it into a file.
        //that file is then parsed appropriately.

        String[] geneIds = null;
        try {
            geneIds = glblFileIO.getFileLines(glblConfiguration.getXmlIn());
        } catch (Exception e) {
            System.out.println("ERROR: Cannot process configuration file. Aborting...");
            e.printStackTrace();
            System.exit(1);
        }

        //Make sure we have some Gene IDs to work with...
        if (geneIds == null) {
            //didn't get any input for some reason..
            System.out.println("Error while reading geneId List.  Aborting operation.");
            //this.cleanUp();
            System.out.flush();
            System.exit(0); //A bit sloppy

        }
        //Collect up the GO terms..
        PbbGoTermCollector pbbGoTerms = new PbbGoTermCollector(glblConfiguration.getGoTerms());
        Hashtable<String, String> gts = pbbGoTerms.retrieveGoTerms(glblParseGoTerms);


        //*** new Code ****
        String input;
        BufferedReader inputLine;
        //Make these global questions at the start.

        try {
            inputLine = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Communicate data to Wiki? (y/n)");
            input = inputLine.readLine();
            //input = "y";
            if (input.compareToIgnoreCase("y") == 0) {
                uploadToWiki = true;
            }

        } catch (IOException ex) {
            System.out.println("Unrecoverable input Error. aborting bot.");
            //this.cleanUp();
            ex.printStackTrace();
            System.exit(1);
        }

        //Future idea:  It might be quite a bit more time effecient to download GNF XML data in a separate thread
        //than the thread that uploads to wikipedia.  Since the wikipedia thread has to sleep for 6 seconds, that time
        //could be easily spent reading data from the GNF server (and also reading data from Wikipedia)...
        //Might be a little tough to impliment though... --jhuss

        int batchSize = 25;
        int numBatch = (int) Math.ceil((double) geneIds.length / (double) batchSize);
        for (int i = 0; i < numBatch; i++) {

            //****DEBUGGING VARIABLE****
            pageBase = this.glblConfiguration.getPageBase();

            System.out.println("*****Starting Batch job " + (i + 1) + " of " + numBatch + " *******");
            int valStart = i * batchSize;
            int valLength;
            if (valStart + batchSize - 1 < geneIds.length) {
                valLength = batchSize;
            } else {
                valLength = geneIds.length - valStart;
            }
            //valstart and end should now point to the 25 range of ids...

            String[] geneIdsBatch = new String[valLength];
            System.out.println("*****Batch Size: " + valLength);
            System.arraycopy(geneIds, valStart, geneIdsBatch, 0, valLength);

            //also modify the log page to be unique.
            glblRunLogPage = glblConfiguration.getWikiLogRun() + "-" + i;

            PbbGNFDataGetter xmlGNFGetter = new PbbGNFDataGetter(glblConfiguration.getDataOut());
            String xmlFile = xmlGNFGetter.getXmlData(geneIdsBatch);

            glblXmlParser = new PbbXML(glblConfiguration.getDataOut(), xmlFile);
            //glblCitation = new PBBCitation(glblBotLog, glblXmlParser);
            String[] simpleFiles = null;
            try {
                simpleFiles = glblXmlParser.xmlDomParse(glblConfiguration.getXmlDecoder(glblConfiguration.getXmlSeek()));
            } catch (Exception ex) {
                System.out.println("Error while Parsing XML.  Closing Log Files.");
                //this.cleanUp();
                ex.printStackTrace();
                System.exit(1);
            }

            PbbData tempData; // = new PBBdata();

            if (simpleFiles == null) {
                System.out.println("Error: No Proteins Parsed from XML file.");
                //glblBotLog.addEntry("SYSTEM", "XML ERROR", "No Proteins Parsed from XML file.", PbbQuickLog.logs.SY);
                break;
            }
            if (simpleFiles.length < 1) {
                System.out.println("Error: No Proteins Parsed from XML file.");
                //glblBotLog.addEntry("SYSTEM", "XML ERROR", "No Proteins Parsed from XML file.", PbbQuickLog.logs.SY);
                break;
            }
            System.out.println("Finished Building Simple Format Files. (" + simpleFiles.length + " Files Total)");
            //glblBotLog.addEntry("SYSTEM", "XML", "Finished building Simple Format Files. (" + simpleFiles.length + " Files Total)", PbbQuickLog.logs.SY);

            //Start web Parsing...
            //Parsed all the data in Simple Format Files.
            this.WikiProcessing(simpleFiles, gts);



        }

        System.out.println("PBB Run Completed.");

        System.out.flush();

        System.exit(0); //A bit sloppy

    }
    //Now global
    private boolean uploadToWiki = false;

    private void WikiProcessing(String[] fileList, Hashtable<String, String> gts) {
        //gts is the GO Terms hashtable.

        PbbWikiCoder myCoder;
        PbbData data;

        if (uploadToWiki) {
            System.out.println("Approval to upload to wiki.");
            try {
                glblWikiCom = new PbbWikiCom(glblConfiguration.getWikiUsername(), glblConfiguration.getWikiPassword(), glblConfiguration.getWikiDomain());

            } catch (Exception ex) {
                System.out.println("!!!ERROR!!! WikiCom errored. Will NOT upload to wiki.");
                glblWikiCom = null;
                ex.printStackTrace();
            }

        } else {
            System.out.println("Will NOT upload to wiki.");
            glblWikiCom = null;

        }

        if (fileList != null) {
            String[] pages = new String[fileList.length];
            int runLength = fileList.length;
            //runLength = 2; //DEBUG
            Date TimeNow = null;
            Date TimeRun = null;
            double waitTime = 0;

            //String directoryEntries = "";
            for (int i = 0; i < runLength; i++) {
                System.out.println("");
                System.out.print("*******Updating Page " + (i + 1) + " of " + fileList.length);

                //ok, now we are going to gather up data for a single protein.
                data = new PbbData();
                data = glblFileIO.getFileAliases(glblConfiguration.getSimpleAlias(), data);
                data = glblFileIO.decodeSimple(fileList[i], data);
                myCoder = new PbbWikiCoder(data, gts);
                //And just like that, we have all the data that we need.

                String protein = data.getValue("Symbol", true).trim();

                String geneNum = data.getValue("Hs_EntrezGene", true).trim();

                if (protein.compareTo("") == 0 || geneNum.compareTo("") == 0) {
                    //we have a bit problem here - this protein has no symbol.
                    //we are just going to skip it.
                    System.out.println("-- Found Protein without Symbol or GeneID... Skipping...");
                    continue;
                }

                //Standard page locations for templates.  
                String page = "Template:PBB/" + geneNum;

                System.out.println(" --(" + protein + "--" + geneNum + ") *******");

                //add in some time remaining estimates here:
                TimeNow = new Date();

                if (TimeRun != null && i > 0) {
                    //Calculate the differences in the times.. convert to seconds.
                    double wait = ((double) TimeNow.getTime() - TimeRun.getTime()) / 1000;
                    //System.out.println("Wait = " + wait);
                    waitTime =
                            (waitTime * (i - 1) + wait) / i;
                    double waitTotal = waitTime * (runLength - i);
                    long waitmins = (long) (waitTotal / 60);
                    long waitsecs = (long) (waitTotal - waitmins * 60);
                    System.out.println("Estimated time remaining: " + waitmins + " minutes, " + waitsecs + " seconds.");
                }
//set for the next run time.

                TimeRun = TimeNow;


                //XXX This is a little messy - might want to clean it up for next time.
                //glblBotLog.addEntry(protein, "INFO", "Beginning work on " + protein + "...", PbbQuickLog.logs.UP);
                //glblBotLog.addEntry("SYSTEM", "INFO", "Beginning work on " + protein + "...", PbbQuickLog.logs.SY);
                //now get the references...
                //String geneNum = data.getValue("Hs_EntrezGene",true).trim();
                /*if (geneNum.compareTo("") != 0) {
                //need to gather up the references..
                System.out.println("Gathering References for Gene...");
                myCoder.setCitationData(glblCitation.getCitations(geneNum));
                System.out.println("Finished Gathering References.");
                }*/

                //now we need to check on the Expression image data...
                //We only look online for it, so we don't need 
                PbbExpression myExp = null;
                Vector<String> expFiles = null;
                try {
                    myExp = new PbbExpression(glblWikiCom);

                    expFiles = myExp.getExpressionFiles(protein, data);
                } catch (Exception ex) {
                    myExp = null;
                    expFiles = null;
                    //glblBotLog.addEntry("SYSTEM", "EXPRESSION", "Error Occured while getting Expression Files: " + ex.getMessage(), PbbQuickLog.logs.SY);
                    System.out.println("Warning: Error while Getting Expression image Files for gene.");

                }

                //Update the expression file list, if there is one to update with...
                if (expFiles != null) {
                    for (int expFilesCount = 0; expFilesCount < expFiles.size(); expFilesCount++) {
                        if (expFilesCount == 0) {
                            data.addData("GeneAtlas_image", expFiles.get(expFilesCount), true);
                        } else {
                            data.addData("GeneAtlas_image", expFiles.get(expFilesCount), false);
                        }

                    }
                }

                //For now I am taking out the PDB image updates - there are some issues with the naming conventions -- Should have
                //thought about it more closely before...  



                /*
                if (uploadToWiki) {
                //Extra PDB image uploading section...
                PDBImage:
                {
                try {
                
                //Ok, lets look on wikipedia for an image...
                
                String pdb = data.getValue("PDB", true).trim();
                String imageName = "PBB_Protein_" + protein + "_image.jpg";
                if (glblWikiCom.wikiHasImage("Image:" + imageName)) {
                //image already exists, so just break out of here.
                data.addData("image", imageName, true);
                if (pdb.compareTo("") != 0) {
                data.addData("image_source", "[[Protein_Data_Bank|PDB]] rendering based on " + pdb + ".", true);
                } else {
                data.addData("image_source", "[[Protein_Data_Bank|PDB]] rendering.", true);
                
                }
                
                break PDBImage;
                }
                
                //String pdb = data.getValue("PDB",true).trim();
                byte[] imageData = null;
                File parentDir = new File(fileList[i]).getParentFile();
                File imageFile = null;
                imageFile =
                new File(parentDir, imageName);
                
                if (pdb.compareTo("") != 0) {
                imageData = glblWikiCom.downloadPdbImage(pdb);
                if (imageData != null) {
                
                //Found a file on the PDB - so upload it to wikipedia.
                //UPLOAD TO WIKIPEDIA.
                //throw new PBBWikiException("DEBUG"); //DEBUG - prevents upload.
                if (debugUpload) {
                glblWikiCom.uploadImage(imageName, imageData, glblWikiCom.pdbImageCopyright);
                } else {
                System.out.println("Skipped Actual File Upload due to debugging.");
                }
                
                glblBotLog.addEntry(protein, "UPLOAD", "Added new Image to wiki: [[Image:" + imageName + "]]", PbbQuickLog.logs.CR);
                //this will include the image in the newly generated pages.
                data.addData("image", imageName, true);
                data.addData("image_source", "[[Protein_Data_Bank|PDB]] rendering based on " + pdb + ".", true);
                
                }
                
                }
                
                } catch (PBBWikiException ex) {
                //if there is any kind of problem, then we will just default to
                // doing nothing.  Basically we just skip this step.
                System.out.println("Warning Occured While Uploading Image:" + ex.getMessage());
                }
                
                }//end PDBImage section
                
                }
                 */


                try {
                    //The input data has been Parsed.  We are going to output a
                    //basic version first.  Then the actual copy of the page Later.
                    outputWikiFile(fileList[i] + ".pbf", myCoder.getWikiCodePB());

                    //Everything from here depends on us communicating with wikipedia...

                    if (uploadToWiki) {
                        //glblPageLocations.put(protein, glblWikiCom.getFullURL(pageBase+page));
                        //glblPageTitles.put(protein,pageBase + page);
                        //Hashtable<String,String> pageDir = glblWikiCom.getPageDirectory(glblConfiguration.getPageDir());

                        //First we are going to see if we have an entry for this gene in the page directory
                        //we do this by geneNum ( <geneNum, Page> )..
                        //boolean redirect = false;
                        // no need to check the directory, we know where the tempalte should be.
                        /*
                        if (pageDir.containsKey(geneNum)) {
                        //We run a quick check to make sure the redirected page is correct...
                        String tmpPage = pageDir.get(geneNum);
                        System.out.println("Found Entry in Page Directory.. Checking Validity.");
                        String tmpDl = glblWikiCom.downloadPage(pageBase + tmpPage);
                        //First lets see if there was any data...
                        if (tmpDl == null) {
                        //FOund a blank page.  So we are going to create a new one.. 
                        page = pageDir.get(geneNum);
                        glblBotLog.addEntry(protein, "WP:REDIRECT", "Protein Redirected to: [[" + pageBase + page + "|" + page + "]]", PbbQuickLog.logs.RD);
                        glblBotLog.addEntry(protein, "HTML:REDIRECT", "Protein Redirected to: " + pageBase + page, PbbQuickLog.logs.RD);
                        redirect =
                        true;
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.Redirected);
                        System.out.println("Page directory gave blank page. Will be creating new page...");
                        //                                         
                        //System.out.println("Page directory gave bad page. Continuing with search...");
                        //                                        glblBotLog.addEntry(protein,"WP:REDIRECT","Page directory gave bad page ([[" +pageBase + tmpPage +"]]).  Continuing with search.. Please correct entry: <" + geneNum + "," + tmpPage + ">." ,PbbQuickLog.logs.RD);
                        //                                        glblBotLog.addEntry(protein,"HTML:REDIRECT","Page directory gave bad page (" +pageBase + tmpPage +").  Continuing with search.. Please correct entry: <" + geneNum + "," + tmpPage + ">." ,PbbQuickLog.logs.RD);
                        //                                        
                        } else if (tmpDl.trim().compareTo("") == 0) {
                        //Found a blank page
                        page = pageDir.get(geneNum);
                        glblBotLog.addEntry(protein, "WP:REDIRECT", "Protein Redirected to: [[" + pageBase + page + "|" + page + "]]", PbbQuickLog.logs.RD);
                        glblBotLog.addEntry(protein, "HTML:REDIRECT", "Protein Redirected to: " + pageBase + page, PbbQuickLog.logs.RD);
                        redirect =
                        true;
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.Redirected);
                        System.out.println("Page directory gave blank page. Will be creating new page...");
                        //                                      
                        } else if ((tmpDl.indexOf("{{PBB") != -1) && tmpDl.matches("(?s).*PBB\\s*\\|\\s*geneid\\s*=\\s*" + geneNum + "\\s*.*")) {
                        //looks like we have a good redirect!
                        page = pageDir.get(geneNum);
                        glblBotLog.addEntry(protein, "WP:REDIRECT", "Protein Redirected to: [[" + pageBase + page + "|" + page + "]]", PbbQuickLog.logs.RD);
                        glblBotLog.addEntry(protein, "HTML:REDIRECT", "Protein Redirected to: " + pageBase + page, PbbQuickLog.logs.RD);
                        redirect =
                        true;
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.Redirected);
                        System.out.println("Page directory gave good page.");
                        //                                      
                        } else {
                        //Skip - other data
                        System.out.println("Page directory gave bad page. Continuing with search...");
                        glblBotLog.addEntry(protein, "WP:REDIRECT", "Page directory gave bad page ([[" + pageBase + tmpPage + "]]).  Continuing with search.. Please correct entry: <" + geneNum + "," + tmpPage + ">.", PbbQuickLog.logs.RD);
                        glblBotLog.addEntry(protein, "HTML:REDIRECT", "Page directory gave bad page (" + pageBase + tmpPage + ").  Continuing with search.. Please correct entry: <" + geneNum + "," + tmpPage + ">.", PbbQuickLog.logs.RD);
                        }
                        
                        }
                         */


                        glblPageLocations.put(protein, glblWikiCom.getFullURL(pageBase + page));
                        glblPageTitles.put(protein, pageBase + page);

                        /*
                        PAGE_SEARCH:
                        {
                        //We are going to put some faith in the operator that the redirected page is the correct page.
                        if (redirect == false) {
                        //boolean acceptablePage = false;
                        int oldProteinBox = -1;
                        
                        //So it becomes necessary to do a search of wikipedia to see if we can find
                        //the proper web page that contains that data... or at least make sure that
                        //we are not creating a page that already exists under a different name
                        
                        Vector<String> searchTerms = new Vector<String>();
                        //Need to cut down the name so that text after a parenthesis or comma is
                        //removed
                        String tmpName = data.getValue("Name", true);
                        
                        String[] tmpNameTokens = tmpName.split("\\s*\\(.*\\)\\s*");
                        tmpName =
                        "";
                        for (int tnt = 0; tnt <
                        tmpNameTokens.length; tnt++) {
                        tmpName += tmpNameTokens[tnt] + " ";
                        }
                        
                        tmpName = tmpName.trim();
                        int index = -1;
                        if ((index = tmpName.indexOf(", ")) != -1) {
                        tmpName = tmpName.substring(0, index);
                        }
                        
                        searchTerms.add(this.toWikiStandard(tmpName)); //.add(data.getValue("Name",true));
                        
                        searchTerms.add(this.toWikiStandard(data.getValue("Symbol", true)));
                        String[] altSymbols = data.getValueList("AltSymbols");
                        for (int v = 0; v <
                        altSymbols.length; v++) {
                        if (altSymbols[v].indexOf("/") == -1 && altSymbols[v].indexOf("?") == -1) {
                        //no repeats, please.
                        if (!searchTerms.contains(this.toWikiStandard(altSymbols[v]))) {
                        searchTerms.add(this.toWikiStandard(altSymbols[v]));
                        }
                        
                        if (!searchTerms.contains(this.toWikiStandard(this.toFormalFormat(altSymbols[v])))) {
                        searchTerms.add(this.toWikiStandard(this.toFormalFormat(altSymbols[v])));
                        }
                        
                        }
                        }
                        //Gonna hold the indexes of potential pages.
                        Vector<Integer> foundPage = new Vector<Integer>();
                        Vector<Integer> otherPage = new Vector<Integer>();
                        //Change in behavior to only supplying a page name *IF and ONLY IF* we find exactly one page
                        //that has a control box in it.
                        
                        
                        //Experiment a Success - no longer need the experiment
                        //if (this.EXPERIMENT){
                        if (matchGridPageData.compareTo("") == 0) {
                        matchGridPageData = "==Page Match Grid==" + lineSep;
                        }
                        //String pageSearchData = "* " + protein + ": ";
                        
                        String pageSearchData = "";
                        //This is to override the matchGridPageData and pageSearchData vars.
                        //String pageTargetData = "";
                        System.out.println("Looking for page - checking " + searchTerms.size() + " potential terms.");
                        System.out.flush();
                        for (int v = 0; v <
                        searchTerms.size(); v++) {
                        System.out.println("Checking " + (v + 1) + " of " + searchTerms.size() + " - " + searchTerms.get(v));
                        if (searchTerms.get(v).trim().compareTo("") == 0) {
                        //Blank info - just skip it
                        continue;
                        }
                        
                        String tmpDl = glblWikiCom.downloadPage(pageBase + searchTerms.get(v));
                        //First lets see if there was any data...
                        if (tmpDl == null) {
                        //No Data
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (No Data); ";
                        continue;
                        
                        }
                        
                        
                        if (tmpDl.compareTo("") == 0) {
                        //No data
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (No Data); ";
                        continue;
                        
                        }
                        
                        
                        if (tmpDl.indexOf("{{hndis}}") != -1) {
                        //Human Name disambiguity page - we are not going to even count this one.
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Human Name DisAmbig - not counted);  ";
                        
                        continue;
                        
                        }
                        
                        //Lets see if this is a DisAmbiguity page...
                        
                        if (tmpDl.toUpperCase().indexOf("{{DISAMBIG}}") != -1) {
                        //yep, we have a disambiguity page - mark it and move on.
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (DisAmbig);  ";
                        otherPage.add(new Integer(v));
                        continue;
                        
                        }
                        
                        
                        if (tmpDl.toUpperCase().indexOf("#REDIRECT") != -1) {
                        //Seems we have a page redirection
                        //Gonna pull out the target..
                        int tmpIndex = tmpDl.toUpperCase().indexOf("#REDIRECT");
                        String tmpRStr = tmpDl.substring(tmpIndex + "#REDIRECT".length()).trim();
                        if (tmpRStr.indexOf("]]") != -1) {
                        //just want the first link present..
                        tmpRStr = tmpRStr.substring(tmpRStr.indexOf("[[") + 2, tmpRStr.indexOf("]]")).trim();
                        }
                        
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Redirect -> " + tmpRStr + ");  ";
                        //We also need to follow redirects - so we are going to add the redirected page to the search
                        tmpRStr =
                        this.toWikiStandard(tmpRStr);
                        if (!searchTerms.contains(tmpRStr)) {
                        searchTerms.add(tmpRStr);
                        }
                        //Since we put the redirect page on the queue, there is really no need to count this page
                        
                        //otherPage.add(new Integer(v));
                        continue;
                        }
                        
                        
                        //Now check for Bot data..
                        //PBBbotCodes tmpCodes = new PBBbotCodes(tmpDl);
                        if (tmpDl.indexOf("{{PBB_Controls") != -1) {
                        //if (tmpCodes.badFormat == false){
                        //Think we found our actual protein page
                        // going to verify by checking the entrez gene number
                        if (tmpDl.matches("(?s).*Hs_EntrezGene\\s*=\\s*" + geneNum + ".*")) {
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Good Codes + Entrez Match); ";
                        foundPage.add(new Integer(v));
                        otherPage.add(new Integer(v));
                        
                        } else {
                        //Basically we have found a data page for a different protein. We just skip it.
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Codes Found, but no match[skip]); ";
                        if (page.compareTo(searchTerms.get(v)) == 0) {
                        //do have a conflict with the page name though, so we do need to put
                        // an "other page" down.
                        otherPage.add(new Integer(v));
                        }
                        
                        }
                        //page = searchTerms.get(v);
                        //foundPage.add(new Boolean("true"));
                        //acceptablePage = true;
                        //foundPage.add(new Integer(v));
                        //otherPage.add(new Integer(v));
                        //glblBotLog.glblDryStatus.put(protein,PbbQuickLog.dryStatus.Found_Match);
                        continue;
                        //break PAGE_SEARCH;
                        }
                        //check for some other kind of protein template..
                        
                        if (tmpDl.toUpperCase().indexOf("{{PROTEIN") != -1) {
                        //found an 'old' protein box.
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Protein Template);  ";
                        otherPage.add(new Integer(v));
                        oldProteinBox =
                        v;
                        //acceptablePage = true;
                        continue;
                        
                        }
                        
                        //Basically we found a normal page - might be the correct one!
                        
                        pageSearchData += "[[" + pageBase + searchTerms.get(v) + "]] (Unknown Data);  ";
                        otherPage.add(new Integer(v));
                        //acceptablePage = true;
                        }
                        
                        glblBotLog.glblProteinTargetPages.put(protein, pageSearchData);
                        matchGridPageData +=
                        "* " + protein + ": " + pageSearchData + lineSep;
                        //                                        experimentalPageData += "* [[" + data.getValue("Name",true) + "]], ";
                        //                                        experimentalPageData += "[[" + data.getValue("Symbol",true) + "]]";
                        //                                        String[] alts = data.getValueList("AltSymbols");
                        //                                        //experimentalPageData += "[[" + data.getValues("AltSymbols", "]] [[ ",true) + "]]" + lineSep + lineSep;
                        //                                        for (int v = 0; v < alts.length; v ++){
                        //                                            if (alts[v].indexOf("/") == -1 && alts[v].indexOf("?") == -1){
                        //                                                experimentalPageData += ", [[" + alts[v] + "]], [[" + this.toFormalFormat(alts[v]) + "]]";
                        //                                            }
                        //                                        }
                        //                                        experimentalPageData += lineSep;
                        //}//End if Experiment
                        
                        //foundPage serves 3 functions: the first is to determine if we found a good page.
                        //the second is that if its size is 0, then we need to make a new page..
                        //the Third is that if its size is 1 and false, then we need to attempt to update that page
                        //if the size is greater than 1 and the total is false, then we have ambiguous pages that we need
                        //to report.
                        
                        //boolean foundTotal = false;
                        //for (int j = 0; j < foundPage.size(); j++) {
                        //    foundTotal = foundTotal || foundPage.get(j).booleanValue();
                        //}
                        //If any of the boolean values were true, then foundTotal will be true.
                        //Of course this won't really matter because we broke this label if any of them were true...
                        
                        
                        
                        
                        
                        if (foundPage.size() == 0) {
                        //No matches at all, probably need to create a new protein then.
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.No_Matches);
                        //glblBotLog.addEntry(protein,"SEARCH","Multiple Conflicting Pages. Need Resolution.",PbbQuickLog.logs.SK);
                        if (otherPage.size() > 0) {
                        //did find other possible pages, so we won't create a new page.
                        glblBotLog.addEntry(protein, "WP:AMBIGUITY", "Did not locate an acceptable page to update.", PbbQuickLog.logs.SK);
                        if (oldProteinBox > -1) {
                        //we found a very possible match, but we won't act on it.
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.High_Match);
                        glblBotLog.glblProteinStatus.put(protein, PbbQuickLog.pStatus.Skip_amb_page);
                        
                        } else {
                        //no good match at all.
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.No_Matches);
                        
                        glblBotLog.glblProteinStatus.put(protein, PbbQuickLog.pStatus.Skip_amb_page);
                        }
                        
                        glblBotLog.addEntry(protein, "BLOCK", StringEscapeUtils.escapeHtml(myCoder.getWikiCodeNew()), PbbQuickLog.logs.SK);
                        
                        System.out.println(protein + ": Protein Status-" + glblBotLog.glblProteinStatus.get(protein).text());
                        continue; //basically just skip this protein.
                        
                        
                        } else {
                        glblBotLog.addEntry(protein, "WP:CREATE", "Found no pages, creating new page.", PbbQuickLog.logs.CR);
                        glblBotLog.glblProteinStatus.put(protein, PbbQuickLog.pStatus.created);
                        
                        }
                        
                        }
                        if (foundPage.size() > 1) {
                        String tmpWp = "";
                        String tmpHtml = "";
                        for (int j = 0; j <
                        foundPage.size(); j++) {
                        tmpWp = tmpWp + "[[" + searchTerms.get(foundPage.get(j).intValue()) + "]] ";
                        tmpHtml =
                        tmpHtml + searchTerms.get(foundPage.get(j).intValue()) + " ";
                        }
                        
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.Page_Conflict);
                        glblBotLog.addEntry(protein, "SEARCH", "Multiple Conflicting Pages. Need Resolution.", PbbQuickLog.logs.SK);
                        glblBotLog.addEntry(protein, "HTML:AMBIGUITY", "More than one potential page found for updating, " + tmpHtml, PbbQuickLog.logs.SK);
                        glblBotLog.addEntry(protein, "WP:AMBIGUITY", "More than one potential page found for updating, " + tmpWp, PbbQuickLog.logs.SK);
                        glblBotLog.addEntry(protein, "BLOCK", StringEscapeUtils.escapeHtml(myCoder.getWikiCodeNew()), PbbQuickLog.logs.SK);
                        
                        glblBotLog.glblProteinStatus.put(protein, PbbQuickLog.pStatus.Skip_amb_page);
                        System.out.println(protein + ": Protein Status-" + glblBotLog.glblProteinStatus.get(protein).text());
                        
                        continue; //basically just skip this protein.
                        
                        
                        }
                        
                        
                        if (foundPage.size() == 1) {
                        //We did find the page.
                        page = searchTerms.get(foundPage.get(0).intValue());
                        glblBotLog.addEntry(protein, "SEARCH REDIRECT", "Control Box Found: " + page, PbbQuickLog.logs.UP);
                        glblBotLog.glblDryStatus.put(protein, PbbQuickLog.dryStatus.Redirected);
                        
                        }
                        // If we made it here, we may be making a new page, or updating a pre-existing control box page.
                        
                        } //end if no redirect
                        
                        }// END PAGE_SEARCH
                         */
                        pages[i] = pageBase + page;
                        String updatedPage = "";

                        //if (!dryRunOnly) {
                        System.out.println("Found page location. Attempting Update...");
                        //    if (redirect == false) {
                        //we didn't have an entry in the protein directory... time to add one.
                        //        directoryEntries += "<" + geneNum + "," + page + "> " + lineSep;
                        //    }

                        updatedPage = this.updateWikiPage(protein, page, data, fileList[i], myCoder);
                        //} else {
                        //    System.out.println("Skipping update due to Dry Run.");
                        //}

                        this.outputWikiFile(fileList[i] + ".pbf.wiki", updatedPage);
                        if (glblProteinStatus.containsKey(protein)) {
                            System.out.println(protein + " (" + geneNum + "): Protein Status - " + glblProteinStatus.get(protein).text());
                        } else {
                            System.out.println(protein + " (" + geneNum + "): Protein Status - Unresolved.");
                            glblProteinStatus.put(protein, pStatus.unresolved);

                        }

                    }//end if Wiki

                } catch (Exception ex) {
                    System.out.println("Error while Processing: " + fileList[i]);
                    System.out.println(ex.getMessage());
                    System.out.println("Continue with next Protein?");
                    //glblBotLog.addEntry("SYSTEM", "PROC_ERROR:", "Error while Processing " + page, PbbQuickLog.logs.SY);

                    //glblBotLog.addEntry(protein, "PROC_ERROR:", "Error while Processing " + page, PbbQuickLog.logs.ER);
                    //glblBotLog.glblProteinStatus.put(protein, PbbQuickLog.pStatus.Skip_error);

                    try {
                        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
                        System.out.flush();
                        String inStr = in.readLine();
                        if (inStr.compareToIgnoreCase("y") != 0) {
                            System.out.println("Processing Aborted. Last Successful Protein: " + fileList[i]);

                            //this.cleanUp();
                            System.exit(1);
                        }

                    } catch (IOException iex) {
                        System.out.println("Unrecoverable IO Error. Last Successful Protein: " + fileList[i] + " -- Aborting...");
                        //this.cleanUp();
                        System.exit(1);

                    }

                }
            //} else  {
            //glblBotLog.addEntry("SYSTEM", "BLANK:", "Protein Name/Symbol is blank.  Skipping " + fileList[i], PbbQuickLog.logs.SY);
//
//            System.out.println("Protein Name/ Symbol is blank. Skipping " + fileList[i]);
//            pages[i] = "DATA ERROR - See Log File.";
//        }


//***LOOP!***
            }//end FOR
            //Time to output the log files..

            //First need to append the log location to the Main log...

            //Time to do a little bookkeeping for the pages we have already built.
            if (uploadToWiki) {
                System.out.println("Processing Log file for Wikipedia...");
                //glblBotLog.addEntry("SYSTEM", "LOG", "Outputting log file to Wikipedia...", PbbQuickLog.logs.SY);
                String mainLog = glblConfiguration.getWikiMainLog();
                //String title = "User:JonSDSUGrad/Sandbox/Auto_Gen2";

                //The actual log title is now retrieved above..
                String title = glblRunLogPage; //glblConfiguration.getWikiLogRun();

                String text = "";
                String old = "";
                try {

                    //Going to try and do a little appending...

                    //Now we have the link to the log file - we overwrite the current log information there.
                    text = "==Log file for [[User:ProteinBoxBot|Protein Box Bot]]==" + lineSep;
                    text = text + "''Log page index: [[" + mainLog + "]]''<br>" + lineSep;
                    text = text + "<big>''' This run of PBB only updated templates.  No other page modifications were made. '''</big>" + lineSep;

                    text = text + getWikiLogProteinStatus(glblPageTitles) + lineSep;
                    text = text + "===Robust Log===" + lineSep;

                    for (int i = 0; i < miniLog.size(); i++) {
                        text = text + miniLog.get(i) + lineSep;

                    }

                    text = text + "END LOG";


                    try {
                        boolean success = false;
                        while (!success) {
                            old = glblWikiCom.downloadPage(title).trim();
                            if (old.compareTo("") == 0) {
                                //Looks like we are uploading a new page...
                                System.out.println("Uploading Log File...");
                                glblWikiCom.uploadPage(title, text, "Automatic update.");
                                success = true;
                            //text = "==Links to [[User:ProteinBoxBot|Protein Box Bot]] Logs==" + lineSep;
                            } else {

                                BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                                System.out.println("Log page: " + title + " already exists, overwrite? (y/n)");
                                String input = inputLine.readLine();
                                //input = "y";
                                if (input.compareToIgnoreCase("y") == 0) {
                                    System.out.println("Uploading Log File...");
                                    glblWikiCom.uploadPage(title, text, "Automatic update.");
                                    success = true;
                                } else {
                                    System.out.println("Please enter a new page title, blank to quit: (previous = " + title + ")");
                                    input = inputLine.readLine();
                                    if (input.compareTo("") == 0) {
                                        throw new IOException("Cannot output log file.");
                                    } else {
                                        title = input;
                                    }

                                }


                            }
                        }
                    } catch (IOException ex) {
                        System.out.println("Unrecoverable Error. aborting bot.");
                        System.out.println("ERROR: " + ex.getMessage());
                        //this.cleanUp();
                        //ex.printStackTrace();
                        System.exit(1);
                    }
//Now to possibly update the protein directory...

//                    if (directoryEntries.compareTo("") != 0) {
//                        //we have a few new entries to add...
//                        System.out.println("Updating Protein Page Directory...");
//                        old =
//                                glblWikiCom.downloadPage(glblConfiguration.getPageDir()).trim();
//                        text =
//                                old + lineSep + directoryEntries;
//                        glblWikiCom.uploadPage(glblConfiguration.getPageDir(), text, "PBB Auto-update.");
//                    }

//now for the Log Index.
                    old = glblWikiCom.downloadPage(mainLog).trim();
                    if (old.compareTo("") == 0) {
                        //Want to add a header if the page is blank...
                        text = "==Links to [[User:ProteinBoxBot|Protein Box Bot]] Logs==" + lineSep;
                    } else {
                        text = old + lineSep;
                    }

                    text = text + "# Log File: [[" + title + "]] - Date: ~~~~~" + lineSep;
                    System.out.println("Appending log file to Main Log...");
                    glblWikiCom.uploadPage(mainLog, text, "Auto-appended next log.");

                    //glblWikiCom.uploadPage(title,text,"Automatic update.");
                    System.out.println("Finished Uploading Log.");
                //}else {
                //    System.out.println("Skipped Actual Upload due to debugging");
                //}
                } catch (Exception ex) {
                    //glblBotLog.addEntry("SYSTEM", "UPLOAD ERROR:", "Problem uploading Log Files list", PbbQuickLog.logs.SY);
                    System.out.println("Error While Uploading Page List:");
                    System.out.println(ex.getMessage());
                }

            }
        }

        return;

    }
//proceedure added to break up the main processing - used to update/create a page on wikipedia.
//returns the text for the updated page.
    private String updateWikiPage(String protein, String page, PbbData data, String fileName, PbbWikiCoder myCoder) throws Exception {

        String editComment = "Automatic Update";

        //check on the global wiki class - can't do anything with it null..
        if (glblWikiCom == null) {
            glblWikiCom = new PbbWikiCom(glblConfiguration.getWikiUsername(), glblConfiguration.getWikiPassword(), glblConfiguration.getWikiDomain());
        }

        String pdb = data.getValue("PDB", true).trim();

        //find out what we have to start with...
        String existingText = glblWikiCom.downloadPage(pageBase + page);
        String newText = "";
        if (existingText == null) {
            existingText = "";
        }
        //Get info about the bot commands...

        PbbPageExaminer botCodes = new PbbPageExaminer(existingText);
        if (existingText.compareTo("") != 0 && botCodes.isBadFormat()) {
            //we have a problem - this protein page is not proper - we don't want to overwrite
            //someone's work, so we issue a warning and spit out a new box in the log. 
            String baseText = myCoder.getWikiCodePB();
            miniLog.add("* '''" + protein + "''': Encountered existing page without Template. Manual Inspection Required : [[" + pageBase + page + "]].");
            miniLog.add("<pre><nowiki> \n" + baseText + "\n </nowiki></pre>");

            glblProteinStatus.put(protein, pStatus.Skip_manual_insp);

            return baseText;
        }

        //If we don't have permission to be on this page, then we just bugger on out.
        if (botCodes.isNoBots()) {
            //Looks like someone doesn't want our bot to touch this page.  No problem.  We'll just output the message and the possible code.'

            String baseText = myCoder.getWikiCodePB();
            miniLog.add("* '''" + protein + "''': Encountered \"No Bot Edits\" for this protein: [[" + pageBase + page + "]].");
            miniLog.add("<pre><nowiki> \n" + baseText + "\n </nowiki></pre>");

            glblProteinStatus.put(protein, pStatus.Skip_no_bots);

            return baseText;
        }

        String imageVal = "";
        String imageCaption = "";

        //Now we need to see if a protein box exists for this page already, and if it does, we need to extract
        //the image data from it.

        Hashtable<String, String> boxFields = botCodes.getBoxFields(PbbPageExaminer.templates.GNF_PROTEIN_BOX);
        //check for existing gene atlas images..
        String[] atlasimages = data.getValueList("GeneAtlas_image");
        if (boxFields.containsKey("GeneAtlas_image1")) {

            if (atlasimages == null) {
                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image1"), false);
            } else if (atlasimages.length < 1) {

                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image1"), false);
            }
        }
        if (boxFields.containsKey("GeneAtlas_image2")) {
            if (atlasimages == null) {
                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image2"), false);
            } else if (atlasimages.length < 2) {
                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image2"), false);
            }
        }
        if (boxFields.containsKey("GeneAtlas_image3")) {
            if (atlasimages == null) {
                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image3"), false);
            } else if (atlasimages.length < 3) {
                data.addData("GeneAtlas_image", boxFields.get("GeneAtlas_image3"), false);
            }
        }



        if (boxFields.containsKey("image")) {
            imageVal = boxFields.get("image");
        }

        if (boxFields.containsKey("image_source")) {
            imageCaption = boxFields.get("image_source");
        }
        //Ok, it has become desirable to ensure that the image actually listed in the protein box does exist,
        //so we'll make the check here..

        if (imageVal.compareTo("") != 0) {
            //Make sure the image exists on Wikipedia...
            if (!glblWikiCom.wikiHasImage("Image:" + imageVal)) {
                //Ok we don't have a valid image, so we will blank the line..
                imageVal = "";
                //Also blank the caption - no valid image, then no valid caption
                imageCaption = "";
            }

        }

        if (imageVal.compareTo("") == 0) {
            //Ok, lets look on wikipedia for an image...
            String imageName = "PBB_Protein_" + protein + "_image.jpg";
            if (glblWikiCom.wikiHasImage("Image:" + imageName)) {
                imageVal = imageName;
                if (pdb.compareTo("") != 0) {
                    imageCaption = "[[Protein_Data_Bank|PDB]] rendering based on " + pdb + ".";
                } else {
                    imageCaption = "[[Protein_Data_Bank|PDB]] rendering.";
                }
            }

        }
        //At this point, we don't have any image for the protein, so we might be able to supply one. 
        //We can only supply one if we have a PDB value.

        if (imageVal.compareTo("") == 0 && pdb.compareTo("") != 0) {
            //didn't find an image on Wikipedia... lets look locally.
            byte[] imageData = null;

            String imageName = "PBB_Protein_" + protein + "_image.jpg";
            imageData = glblWikiCom.downloadPdbImage(pdb);
            if (imageData != null) {
                imageVal = imageName;
                try {
                    //UPLOAD TO WIKIPEDIA.

                    if (debugUpload) {
                        glblWikiCom.uploadImage(imageName, imageData, PbbWikiCom.pdbImageCopyright);
                    } else {
                        System.out.println("Skipped Actual File Upload due to debugging.");
                    }

                //glblBotLog.addEntry(protein, "UPLOAD", "Added new Image to wikiCreated new protein page: <a href=" + glblWikiCom.getFullURL(pageBase + page) + ">" + pageBase + page + "</a>", PbbQuickLog.logs.CR);
                } catch (Exception ex) {
                    //if there is any kind of problem, then we will just default to
                    //no image data available.
                    imageVal = "";
                    imageCaption = "";
                }
                //Now make sure the image is there..
                if (!glblWikiCom.wikiHasImage("Image:" + imageName)) {
                    imageVal = "";
                    imageCaption = "";
                }

            }
        }

        //after all that, we place the valus in the data if they exist...
        // We also overwrite any previous image data that might have been upload earlier..
        if (imageVal.compareTo("") != 0) {
            //looks like we have image data.
            data.addData("image", imageVal, true);
        }
        if (imageCaption.compareTo("") != 0) {
            //looks like we have image data.
            data.addData("image_source", imageCaption, true);
        }


        //gather up a new page..

        if (existingText.trim().compareTo("") == 0) {
            //We have a blank page - we are going to create it!
            String baseText = myCoder.getWikiCodePB();

            if (debugUpload) {
                glblWikiCom.uploadPage(pageBase + page, baseText, "New Page Created by Protein Box Bot");
            } else {
                System.out.println("Skipped Actual Upload due to debugging");
            }
            miniLog.add("* '''" + protein + "''': Created new template Page: [[" + pageBase + page + "]].");

            glblProteinStatus.put(protein, pStatus.created);
            return baseText;

        }

        
        
        //If we get to here, then we will likely be uploading an update.

        int pBoxS = botCodes.getBoxBegin(PbbPageExaminer.templates.GNF_PROTEIN_BOX);
        int pBoxE = botCodes.getBoxEnd(PbbPageExaminer.templates.GNF_PROTEIN_BOX);
        String pBoxD = myCoder.getWikiCodePB();

        //only update protein Box, while retaining surrounding text (though there should be none!)
        newText += existingText.substring(0, pBoxS);
        newText += pBoxD;
        newText += existingText.substring(pBoxE);
        newText = newText.trim();
        String test1 = "";
        String test2 = "";
        //have to get a little fancy to clear out those random linefeeds..
        String[] tokes = newText.trim().split("[\n\r]");
        for (int x = 0; x < tokes.length; x++) {
            if (tokes[x].trim().compareTo("") != 0) {
                test1 += tokes[x].trim() + "\n";
            }
        }

        tokes = existingText.trim().split("[\r\n]");
        for (int x = 0; x < tokes.length; x++) {
            if (tokes[x].trim().compareTo("") != 0) {
                test2 += tokes[x].trim() + "\n";
            }
        }


        editComment = "PBB Automatic Update: Updated Protein Box";
        if (test1.compareTo(test2) == 0) {
            System.out.println("No Update required, data did not change.");
            miniLog.add("* '''" + protein + "''': No Update Needed (Data did not change): [[" + pageBase + page + "]].");
            glblProteinStatus.put(protein, pStatus.Skip_no_change);
        } else {

            if (debugUpload) {
                glblWikiCom.uploadPage(pageBase + page, newText, editComment);
            } else {
                System.out.println("Skipped Actual Upload due to debugging");
            }
            miniLog.add("* '''" + protein + "''': Updated template Page: [[" + pageBase + page + "]].");

            glblProteinStatus.put(protein, pStatus.updated);
        }

        return newText;
    }//END METHOD

    private void outputWikiFile(String filename, String data) {
        if (glblFileIO == null) {
            glblFileIO = new PbbFileIO();
        }

        try {
            glblFileIO.initOutFile(filename);
            glblFileIO.writeFileln(data);
            glblFileIO.killStreams();
        } catch (IOException ex) {
            System.err.println("Error while outputting to file: " + filename);

        }

    }//END METHOD

    public static void printHelp() {
        //prints some help to the command line.
        System.out.println("Protein Box Bot");
        System.out.println("-------------------------------------------------------");
        System.out.println("Command line options:");
        System.out.println("-h /h h help -help  Display this help information.");
        System.out.println("-f <file>  Sets the location of the configuration file.");
        System.out.println("-parsegt Forces a new parse of the go terms xml file. ");
        System.out.println("-------------------------------------------------------");
        System.out.println("");

    }//END METHOD

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // Handle code start logic here:

        //One possibility: Command-line only.
        //Regardless we will need a configuration filename pointing to the configuration
        //file for the program (this file contains items such as location of XML files
        //for protein info, and possible server address/instrctions for wikipedia).

        boolean uGui = true;
        boolean abortProgram = false; //We will abort if the command line has trouble.

        String confLocation = "";
        boolean pgt = false;
        if (args.length > 0) {

            for (int i = 0; i < args.length; i++) {

                System.out.println("Argument: " + args[i].toUpperCase());
                if (args[i].toUpperCase().compareTo("-F") == 0) {
                    //next argument should be the file location.
                    if (i + 1 >= args.length) {
                        //Got the flag, but no following argument.. Abort!
                        abortProgram = true;
                        printHelp();

                        break;

                    } else {
                        confLocation = args[i + 1];
                        i++; //So we skip past the location on the next loop.

                    }

                } else if (args[i].toUpperCase().compareTo("-PARSEGT") == 0) {
                    //force a parse of the go terms file.
                    pgt = true;

                } else {
                    //Got a strange command - just error with the help screen.

                    abortProgram = true;
                    break;

                }

            } //end argument loop

        } else {
            abortProgram = true;

        }


        if (confLocation.compareTo("") == 0) {
            abortProgram = true;

        }


        if (abortProgram == false) {

            PbbUpdater PbbUp = new PbbUpdater(confLocation, pgt);

        } else {
            printHelp();
        }

    }

    public String getWikiLogProteinStatus(Hashtable<String, String> locations) {
        //String lineSep = System.getProperty("line.separator");
        String data = "";
        Set<String> mySet = this.glblProteinStatus.keySet();
        Iterator<String> myIt = mySet.iterator();

        EnumMap<pStatus, String> sections = new EnumMap<pStatus, String>(pStatus.class);

        //clear up the strings.


        for (pStatus ps : pStatus.values()) {
            sections.put(ps, "");
            ps.setPCount(0);
        }
        //data = data + "== Protein Status Log - Date: ~~~~~ ==" + lineSep;
        while (myIt.hasNext()) {
            String protein = myIt.next();
            String title = protein;
            if (locations != null) {

                if (locations.containsKey(protein)) {
                    //get the location data for the page.
                    title = "[[" + locations.get(protein) + "|" + protein + "]]";
                }
            }
            pStatus ps = glblProteinStatus.get(protein);
            if (ps != null) {
                String tmpStr = sections.get(ps);
                tmpStr = tmpStr + "| " + title + " " + lineSep;
                ps.setPCount(ps.getPCount() + 1);
                if (ps.getPCount() % 5 == 0 && ps.getPCount() > 0) {
                    tmpStr = tmpStr + "|-" + lineSep;
                }

                sections.put(ps, tmpStr);
            }

        }
        for (pStatus ps : pStatus.values()) {
            String tmpStr = sections.get(ps);
            if (tmpStr.compareTo("") != 0) {
                tmpStr = "====" + ps.text() + " (" + ps.getPCount() + ")====" + lineSep + "{| width = 750px" + lineSep + tmpStr + lineSep + "|}" + lineSep;
                data = data + tmpStr;
            }

        }
        return data;
    }
}
